//通用头文件
#ifndef __UNIVERSAL__H
#define __UNIVERSAL__H

#include<iostream>
#include<utility>
#include<cstdlib>
#include<ctime>
#include<tuple>
#include"ExceptionDefinition.hpp"
using namespace std;

namespace NgSiuKei {

//二叉树遍历类型
enum BINARY_TREE_ORDER_TYPE {
    ORDER_TYPE_PRE,     //前
    ORDER_TYPE_IN,      //中
    ORDER_TYPE_POST,    //后
    ORDER_TYPE_LEVEL,   //层序
};

//二叉树节点颜色（用于红黑树）
enum BinaryTreeNodeColor : int {
    BinaryTreeNodeColorRed = 0,
    BinaryTreeNodeColorBlack,
};

//图类型
enum GraphType: int {
    GraphTypeUndirectedAndUnweighted = 0,   //无向无权图
    GraphTypeUndirectedAndWeighted = 1,     //无向有权图
    GraphTypeDirectedAndUnweighted = 10,    //有向无权图
    GraphTypeDirectedAndWeighted = 11,      //有向有权图
};

//图路径类型
enum GraphRoadType {
    GraphRoadTypeUndirected,    //无向
    GraphRoadTypeDirected,      //有向
};

//获取最小生成树算法类型
enum GetMinSpanningTreeFuncType {
    GetMinSpanningTreeFuncTypePrim,    //Prim算法
    GetMinSpanningTreeFuncTypeKruskal  //Kruskal算法
};

//获取最大流通量
enum GetMaximunFlowFuncType {
    GetMaximunFlowFuncTypeNormal,           //普通不靠谱算法
    GetMaximunFlowFuncTypeFordFulkerson,    //Ford-Fulkerson算法
    GetMaximunFlowTypeEdmondsKarp,          //Edmonds-Karp算法
    GetMaximunFlowTypeDinic,                //Dinic's算法
};

//无权默认权重
#define Unweighted 0

#define MAX_SIZE 12

//一些缩写
#define U_L_L unsigned long long
#define P_TC_I pair<TheClass, U_L_L>

//Debug
#define debugOut cout<<"[wsq] ["<<__FILE__ << " : " <<__LINE__<<"] "

//////////////////////////----- 元组tuple重载<< -------/////////////////////////////

/*
抄自：https://blog.csdn.net/sinat_29173167/article/details/89930463
*/

// 由于std::get<size_t>(t)的语法中是size_t必须在编译的时候确定，所以无法传左值。
// 借助模板中的可变模板参数递归实现
template<typename Tuple, size_t N>
struct tuple_print {
    static void print(const Tuple& t, ostream& os) {
        tuple_print<Tuple, N-1>::print(t, os);
        os << ", " << get<N-1>(t); 
    }
};
// 类模板的特化版本
template<typename Tuple>
struct tuple_print<Tuple, 1> {
    static void print(const Tuple& t, ostream& os) {
        os << get<0>(t); 
    }
};
// operator<<
template<typename... Args>
ostream& operator<<(ostream& os, const tuple<Args...>& t) {
	os << "[";
    tuple_print<decltype(t), sizeof...(Args)>::print(t, os);
    os << "]";
    return os;
}

//////////////////////////----- pair重载<< -------/////////////////////////////

/*
抄自：https://www.zhihu.com/question/464114726/answer/1945389516
*/

template<class T, class U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}

//////////////////////////////////////////////////////////////////////////////////

}

#endif